import { _decorator, Component, Node, Tween, Vec3, tween, Animation } from "cc"
import { AudioManager } from "../framework/AudioManager"

import { Prefab } from "cc"
import ResManager from "../framework/ResManager"
import { instantiate } from "cc"
import { GlobalData } from "../GlobalData"
import { JsonAsset } from "cc"
import { ClientEvent } from "../framework/ClientEvent"
import { Monster } from "./Monster"
import { Label } from "cc"
import { EventTouch } from "cc"
import { Vec2 } from "cc"
import { UITransform } from "cc"
import { util } from "../util/util"
import { Player } from "./Player"
import { Sprite } from "cc"
import { MonsterHero } from "./MonsterHero"
import { GamePlayerDebris } from "./GamePlayerDebris"
import { EffectManager } from "./EffectManager"
import { MonsterBoss } from "./MonsterBoss"
import { GUIDE_STATE } from "../framework/constant"
import { GuideHand } from "./GuideHand"
const { ccclass, property } = _decorator

const Dis_Touch: number = 120
@ccclass("GameManager")
export class GameManager extends Component {
  private nodeDamageParent: Node = null

  private nodeHpParent: Node = null

  private nodeBulletParent: Node = null

  private nodeRoleParent: Node = null

  private nodePlayerParent: Node = null

  private nodeEffectParent: Node = null

  private nodeTouchLayerManager: Node = null

  private arrNodeTouch: Node[] = []

  private arrRolePlayer: Player[] = [null, null, null, null, null]

  private isGuideTouch: boolean = false

  @property(Node)
  public nodeGameUI: Node = null

  @property(Node)
  public nodeGameMask: Node = null

  protected onLoad(): void {
    // console.log(navigator.language.toLowerCase())
    this.playMusic()
    GlobalData.instance.nodeGame = this.node
    this.nodeBulletParent = this.node.getChildByName("bulletParent")
    this.nodeHpParent = this.node.getChildByName("hpParent")
    this.nodeDamageParent = this.node.getChildByName("damageParent")
    this.nodeRoleParent = this.node.getChildByName("roleParent")
    this.nodePlayerParent = this.node.getChildByName("playerParent")
    this.nodeTouchLayerManager = this.node.getChildByName("nodeTouchLayer")
    this.nodeEffectParent = this.node.getChildByName("effectParent")

    for (let key in this.nodeTouchLayerManager.children) {
      const node = this.nodeTouchLayerManager.children[key]
      this.arrNodeTouch.push(node)
      node.active = false
    }
    this.isGuideTouch = true
  }
  start() {
    GlobalData.instance.coinValue = 10000
    GlobalData.instance.gemValue = 0
    GlobalData.instance.expValue = 0

    GlobalData.instance.numMonsterSlow = 0
    // GlobalData.instance.gamePlayerHp = 500
    this.initGameData()

    // this.scheduleOnce(() => {
    //   this.onInitNewRoleDebris(2, new Vec3(400, 0))
    // })
  }

  protected onEnable(): void {
    ClientEvent.on("onGameStart", this.onGameStart, this)
    ClientEvent.on("onGameOver", this.onGameOver, this)
    ClientEvent.on("onInitDamage", this.onInitDamage, this)
    ClientEvent.on("onRefuseData", this.onRefuseData, this)
    ClientEvent.on("onInitJsonData", this.onInitJsonData, this)

    ClientEvent.on("onMonsterDie", this.onMonsterDie, this)
    ClientEvent.on("onInitMoney", this.onInitMoney, this)

    ClientEvent.on("onPlayerDie", this.onPlayerDie, this)
    ClientEvent.on("onInitPlayerRole", this.onInitPlayerRole, this)

    ClientEvent.on("onMonsterBeAttackEffect", this.onMonsterBeAttackEffect, this)
    ClientEvent.on("onSkillUpgradeChange", this.onSkillUpgradeChange, this)
    ClientEvent.on("onInitNewRoleDebris", this.onInitNewRoleDebris, this)
    ClientEvent.on("onPlayerTextComplete", this.onPlayerTextComplete, this)
    ClientEvent.on("onShark", this.shake, this)

    this.nodeTouchLayerManager.on(Node.EventType.TOUCH_START, this._touchStartEvent, this)
    this.nodeTouchLayerManager.on(Node.EventType.TOUCH_MOVE, this._touchMoveEvent, this)
    this.nodeTouchLayerManager.on(Node.EventType.TOUCH_END, this._touchEndEvent, this)
    this.nodeTouchLayerManager.on(Node.EventType.TOUCH_CANCEL, this._touchEndEvent, this)
  }

  protected onDisable(): void {
    ClientEvent.off("onGameStart", this.onGameStart, this)
    ClientEvent.off("onInitDamage", this.onInitDamage, this)
    ClientEvent.off("onRefuseData", this.onRefuseData, this)
    ClientEvent.off("onInitJsonData", this.onInitJsonData, this)

    ClientEvent.off("onMonsterDie", this.onMonsterDie, this)
    ClientEvent.off("onPlayerDie", this.onPlayerDie, this)
    ClientEvent.off("onInitPlayerRole", this.onInitPlayerRole, this)
    ClientEvent.off("onMonsterBeAttackEffect", this.onMonsterBeAttackEffect, this)
    ClientEvent.off("onSkillUpgradeChange", this.onSkillUpgradeChange, this)
    ClientEvent.off("onInitNewRoleDebris", this.onInitNewRoleDebris, this)
    ClientEvent.off("onPlayerTextComplete", this.onPlayerTextComplete, this)
    ClientEvent.off("onShark", this.shake, this)

    this.nodeTouchLayerManager.off(Node.EventType.TOUCH_START, this._touchStartEvent, this)
    this.nodeTouchLayerManager.off(Node.EventType.TOUCH_MOVE, this._touchMoveEvent, this)
    this.nodeTouchLayerManager.off(Node.EventType.TOUCH_END, this._touchEndEvent, this)
    this.nodeTouchLayerManager.off(Node.EventType.TOUCH_CANCEL, this._touchEndEvent, this)
  }

  convertToNodeSpaceAR(touchPos: Vec2) {
    let uiTransform = this.nodeTouchLayerManager.getComponent(UITransform)
    return uiTransform.convertToNodeSpaceAR(new Vec3(touchPos.x, touchPos.y))
  }

  private _isTouch: boolean = false
  private _isCanTouch: boolean = true
  private curTouchIndex: number = -1

  private _touchStartEvent(event: EventTouch) {
    if (!this._isCanTouch || this.isGuideTouch) return
    let touchPos = this.convertToNodeSpaceAR(event.getUILocation())
    for (let i: number = 0; i < this.arrNodeTouch.length; i++) {
      const node = this.arrNodeTouch[i]
      const dis = util.getTwoPosXYLength(touchPos.x, touchPos.y, node.position.x, node.position.y)
      if (dis < Dis_Touch) {
        this.curTouchIndex = i
        break
      }
    }
    if (this.curTouchIndex !== -1) {
      let player = this.arrRolePlayer[this.curTouchIndex]
      if (player && player.getIsCanTouch()) {
        player.onTouchStart()
        player.node.setSiblingIndex(this.nodePlayerParent.children.length - 1)
        this._isTouch = true
        const uiTransform: UITransform = this.nodePlayerParent.getComponent(UITransform)
        const pos = uiTransform.convertToNodeSpaceAR(new Vec3(event.getUILocation().x, event.getUILocation().y))
        this.arrRolePlayer[this.curTouchIndex].node.setPosition(pos)

        //光柱
        for (let i = 0; i < this.arrNodeTouch.length; i++) {
          if (i == this.curTouchIndex) {
            this.arrNodeTouch[i].active = false
          } else {
            this.arrNodeTouch[i].active = true
            this.changeTouchNodeState(this.arrNodeTouch[i], 0)
          }
        }
      } else {
        this.curTouchIndex = -1
      }
    }
  }
  private _touchMoveEvent(event: EventTouch) {
    // return
    if (!this._isTouch || !this._isCanTouch || this.curTouchIndex == -1) return
    const uiTransform: UITransform = this.nodePlayerParent.getComponent(UITransform)
    const pos = uiTransform.convertToNodeSpaceAR(new Vec3(event.getUILocation().x, event.getUILocation().y))
    this.arrRolePlayer[this.curTouchIndex].node.setPosition(pos)
    let touchPos = this.convertToNodeSpaceAR(event.getUILocation())
    let endTouchIndex: number = -1
    for (let i: number = 0; i < this.arrNodeTouch.length; i++) {
      const node = this.arrNodeTouch[i]
      const dis = util.getTwoPosXYLength(touchPos.x, touchPos.y, node.position.x, node.position.y)
      if (dis < Dis_Touch) {
        endTouchIndex = i
        break
      }
    }

    //光柱
    for (let i = 0; i < this.arrNodeTouch.length; i++) {
      if (i == this.curTouchIndex) {
        this.arrNodeTouch[i].active = false
      } else if (endTouchIndex == i) {
        this.arrNodeTouch[i].active = true
        this.changeTouchNodeState(this.arrNodeTouch[i], 1)
      } else {
        this.arrNodeTouch[i].active = true
        this.changeTouchNodeState(this.arrNodeTouch[i], 0)
      }
    }
  }

  private _touchEndEvent(event: EventTouch) {
    // return
    if (!this._isTouch || !this._isCanTouch) return
    this._isTouch = false

    let touchPos = this.convertToNodeSpaceAR(event.getUILocation())
    let endTouchIndex: number = -1
    for (let i: number = 0; i < this.arrNodeTouch.length; i++) {
      const node = this.arrNodeTouch[i]
      const dis = util.getTwoPosXYLength(touchPos.x, touchPos.y, node.position.x, node.position.y)
      if (dis < Dis_Touch) {
        endTouchIndex = i
        break
      }
    }

    if (endTouchIndex !== -1 && this.curTouchIndex !== endTouchIndex) {
      let startPlayer = this.arrRolePlayer[this.curTouchIndex]
      let endPlayer = this.arrRolePlayer[endTouchIndex]
      if (!endPlayer || (endPlayer && endPlayer.getIsCanTouch())) {
        this.arrRolePlayer[this.curTouchIndex] = endPlayer
        this.arrRolePlayer[endTouchIndex] = startPlayer
        this.recoverRolePos(this.curTouchIndex)
        this.recoverRolePos(endTouchIndex)
      } else {
        this.recoverRolePos(this.curTouchIndex)
      }
      this.overGuideChangeRole()
    } else {
      this.recoverRolePos(this.curTouchIndex)
    }
    this.curTouchIndex = -1
    for (let i = 0; i < this.arrNodeTouch.length; i++) {
      this.arrNodeTouch[i].active = false
    }
  }

  private changeTouchNodeState(node: Node, index: number) {
    const nodeNormal = node.getChildByName("nodeEffectNormal")
    const nodeSelect = node.getChildByName("nodeEffectSelect")
    nodeNormal.active = index == 0
    nodeSelect.active = index == 1
  }

  private recoverRolePos(index: number) {
    if (this.arrRolePlayer[index] && this.arrRolePlayer[index].node) {
      const pos = this.arrNodeTouch[index].getPosition()
      this.arrRolePlayer[index].node.setPosition(pos)
      this.arrRolePlayer[index].onTouchEnd()
    }
  }

  private initGameData() {
    let monsterDataPromise = this.loadGameConfig("configs/monsterData")
    let levelDataPromise = this.loadGameConfig("configs/levelData")
    let roleDataPromise = this.loadGameConfig("configs/roleData")
    Promise.all([monsterDataPromise, levelDataPromise, roleDataPromise])
      .then(([monsterData, levelData, roleData]) => {
        GlobalData.instance.monsterData = monsterData.json
        GlobalData.instance.levelData = levelData.json
        GlobalData.instance.roleData = roleData.json
        GlobalData.instance.curLevel = 0
        this.firstInitRole()
        ClientEvent.emit("onGameStart")
      })
      .catch((error) => {
        console.error("加载数据时发生错误:", error)
      })
  }

  protected loadGameConfig(url: string): Promise<JsonAsset> {
    return new Promise((resolve, reject) => {
      ResManager.instance.loadRes(url, JsonAsset, (err, jsonAsset: JsonAsset) => {
        if (!err) {
          resolve(jsonAsset) // 成功时解析 Promise
        } else {
          reject(err) // 失败时拒绝 Promise
        }
      })
    })
  }

  private firstInitRole() {
    this.initPlayerRole(1, null)

    // this.initPlayerRole(2, false)
    // this.initPlayerRole(3, false)
    // this.initPlayerRole(4, false)
    // this.initPlayerRole(5, false)

    this.scheduleOnce(this.initChatFrame, 1)
  }

  /**聊天对话框 */
  private initChatFrame() {
    ResManager.instance.loadRes("prefabs/game/gameObject/nodeChatFrame", Prefab, (err, prefab: Prefab) => {
      if (prefab) {
        const nodeChatFrame = instantiate(prefab)
        this.nodeEffectParent.addChild(nodeChatFrame)
        const pos = GlobalData.instance.arrNodePlayerRole[0].getPosition()
        nodeChatFrame.setPosition(pos.x, pos.y + 65)
      }

      this.scheduleOnce(() => {
        this.isGuideTouch = false
      }, 2)
    })
  }

  private onInitPlayerRole(roleId: number, pos: Vec3) {
    this.initPlayerRole(roleId, pos)
  }

  private initPlayerRole(roleId: number, posEffect: Vec3 = null) {
    ResManager.instance.loadRes("prefabs/game/role/role" + roleId, Prefab, (err, prefab: Prefab) => {
      const nodeRole = instantiate(prefab)
      const player: Player = nodeRole.addComponent(Player)
      player.init(roleId)

      let curIndex: number = 0
      for (; curIndex < this.arrRolePlayer.length; curIndex++) {
        if (!this.arrRolePlayer[curIndex]) {
          this.arrRolePlayer[curIndex] = player
          break
        }
      }
      const pos = this.arrNodeTouch[curIndex].getPosition()
      nodeRole.setPosition(pos)
      if (posEffect) {
        const time: number = 0.3
        this.initStreakEffect(posEffect, pos, time)
        this.scheduleOnce(() => {
          this.nodePlayerParent.addChild(nodeRole)
          player.playIntoAction()
          //新手指导部分
          if (GlobalData.instance.gCurrGuide == GUIDE_STATE.ROLE_DEBRIS) {
            GlobalData.instance.gCurrGuide = GUIDE_STATE.ROLE_CHANGER_ROLE
            this.scheduleOnce(() => {
              let firstPos: Vec3 = null
              for (let i = this.arrRolePlayer.length - 1; i >= 0; i--) {
                this.arrNodeTouch[i].active = true
                if (!this.arrRolePlayer[i] && !firstPos) {
                  firstPos = this.arrNodeTouch[i].getPosition()
                  this.changeTouchNodeState(this.arrNodeTouch[i], 1)
                } else {
                  this.changeTouchNodeState(this.arrNodeTouch[i], 0)
                }
              }
              this.onGuideChangeRole(nodeRole.getPosition(), firstPos)
              this.gamePause()
              this.nodeGameMask.active = true
              this.nodeGameMask.alpha = 0
              new Tween(this.nodeGameMask).to(0.3, { alpha: 1 }).start()
              this.scheduleOnce(this.gameResume, 5)
            }, 0.5)
          }
        }, time + 0.1)
        this.scheduleOnce(() => {
          EffectManager.instance.playEffectRoleOut(pos)
        }, time - 0.2)
      } else {
        this.nodePlayerParent.addChild(nodeRole)
      }
    })
  }
  private initStreakEffect(pos: Vec3, movePos: Vec3, time: number) {
    ResManager.instance.loadRes("prefabs/game/gameObject/nodeStreak", Prefab, (err, prefab: Prefab) => {
      if (prefab) {
        const node = instantiate(prefab)
        this.nodeEffectParent.addChild(node)
        node.setPosition(pos)
        new Tween(node)
          .to(time, { position: movePos })
          .call(() => {
            node.destroy()
          })
          .start()
      }
    })
  }

  private onGameStart() {
    this.initMonsterLevel()
    GlobalData.instance.isGameStart = true
  }
  private onGameOver() {}

  private gamePause() {
    GlobalData.instance.isGamePause = true
    ClientEvent.emit("onGamePause")
  }

  private gameResume() {
    this.unschedule(this.gameResume)
    this.nodeGameMask.active = false
    GlobalData.instance.isGamePause = false
    ClientEvent.emit("onGameResume")
  }

  private gameOver() {
    GlobalData.instance.isGameOver = true
    ClientEvent.emit("onGameOver")
  }

  private onRefuseData() {
    // return
    // if(GlobalData.instance.isGamePause){
    //   this.gameResume()
    // }else{
    //   this.gamePause()
    // }
    // this.onInitNewRoleDebris(2, new Vec3(0, 0))

    while (GlobalData.instance.arrNodeMonster.length > 0) {
      GlobalData.instance.arrNodeMonster[0].destroy()
      GlobalData.instance.arrNodeMonster.splice(0, 1)
    }
    this.onGameStart()
  }

  private onInitJsonData() {
    let ojectJson = []
    for (let i: number = 0; i < 3; i++) {
      let oject = {
        monsterType: "monster" + (i + 1),
        pos: [],
      }
      ojectJson.push(oject)
    }
    for (let i: number = 0; i < GlobalData.instance.arrNodeMonster.length; i++) {
      const node = GlobalData.instance.arrNodeMonster[i]
      let name = node.name
      for (let j: number = 0; j < ojectJson.length; j++) {
        if (name == ojectJson[j].monsterType) {
          ojectJson[j].pos.push([Math.round(node.positionX), Math.round(node.positionY)])
          break
        }
      }
    }

    console.log(ojectJson)
  }

  private onMonsterDie(goldDrop: number, pos: Vec3) {
    GlobalData.instance.curMonsterCount++
    GlobalData.instance.expValue++
    this.randomGem(pos)
    this.playNodeRewardCoinValue(goldDrop, new Vec3(pos.x + Math.random() * 80 - 40, pos.y + 50))
    EffectManager.instance.playActionMonsterDie(pos)
    GlobalData.instance.coinValue += goldDrop
    if (GlobalData.instance.arrNodeMonster.length <= 0) {
      this.unschedule(this.initWaveMonster)
      this.initWaveMonster()
    }
  }

  private onInitMoney(goldDrop: number, pos: Vec3) {
    // this.randomGem(pos)
    // this.playNodeRewardCoinValue(goldDrop, new Vec3(pos.x + Math.random() * 80 - 40, pos.y + 50))
    GlobalData.instance.coinValue += goldDrop * 2
  }

  private randomGem(pos: Vec3) {
    const random = Math.random()
    if (random < 0.02) {
      ClientEvent.emit("onGameCreateGem", pos)
    }
  }

  private onPlayerDie(node: Node) {
    this.overGuideChangeRole()
    const indexOfNode = GlobalData.instance.arrNodePlayerRole.indexOf(node)
    if (indexOfNode !== -1) {
      GlobalData.instance.arrNodePlayerRole.splice(indexOfNode, 1)
    }
    const player: Player = node.getComponent(Player)
    const indexOfRole = this.arrRolePlayer.indexOf(player)
    let pos = node.getPosition()
    if (indexOfRole !== -1) {
      pos = this.arrNodeTouch[indexOfRole].getPosition()
    }

    ResManager.instance.loadRes("prefabs/game/gameObject/nodeTombstone", Prefab, (err, prefab: Prefab) => {
      if (prefab) {
        const nodeTombstone = instantiate(prefab)
        this.nodeRoleParent.addChild(nodeTombstone)
        nodeTombstone.setPosition(pos)
        nodeTombstone.alpha = 0
        new Tween(nodeTombstone).to(0.3, { alpha: 1 }).start()
      }
    })

    let isOver: boolean = true
    for (let key in this.arrRolePlayer) {
      if (this.arrRolePlayer[key] && !this.arrRolePlayer[key].isDie) {
        isOver = false
        break
      }
    }

    if (isOver) {
      this.gameOver()
    }
  }

  /**新角色碎片特效 */
  private onInitNewRoleDebris(roleId: number, pos: Vec3) {
    ResManager.instance.loadRes("prefabs/game/gameObject/nodePlayerDebris", Prefab, (err, prefab: Prefab) => {
      if (prefab) {
        const nodePlayerDebris = instantiate(prefab)
        this.nodeEffectParent.addChild(nodePlayerDebris)
        nodePlayerDebris.setPosition(pos)
        const gamePlayerDebris: GamePlayerDebris = nodePlayerDebris.getComponent(GamePlayerDebris)
        gamePlayerDebris.init(roleId)

      }
    })
  }

  private onPlayerTextComplete() {
    if (0 == GlobalData.instance.numMonsterSlow) {
      GlobalData.instance.numMonsterSlow = 1
    }
  }

  private initWaveMonster() {
    GlobalData.instance.curLevel++
    if (GlobalData.instance.curLevel < GlobalData.instance.levelData.length) {
      this.initMonsterLevel(2.3)
      this.scheduleOnce(() => {
        ClientEvent.emit("createBossComingEffect", GlobalData.instance.curLevel - 1)
      })
    }
  }

  private initMonsterLevel(time: number = 0) {
    // return
    const level = GlobalData.instance.curLevel
    let levelData: any[] = GlobalData.instance.levelData[level]

    GlobalData.instance.maxMonsterCount = 0

    for (let i: number = 0; i < levelData.length; i++) {
      this.loadMonsterWithData(levelData[i], time)
      GlobalData.instance.maxMonsterCount += levelData[i].pos.length
    }
    GlobalData.instance.curMonsterCount = 0
    ClientEvent.emit("onMonsterWaveComplete")
    // for (let i: number = 1; i < 4; i++) {
    //   this.loadMonsterWithData({ monsterType: "monster" + i, pos: [[1, 1]] }, time)
    // }
  }

  /**根据关卡数据，先加载怪物资源，再实例化怪物 */
  private loadMonsterWithData(data: { monsterType: string; pos: number[][] }, time: number = 0) {
    ResManager.instance.loadRes("prefabs/game/role/" + data.monsterType, Prefab, (err, prefab: Prefab) => {
      // if (data.monsterType.indexOf("role") !== -1) return
      // const random: number = 100
      // for (let i: number = 0; i < random; i++) {
      //   let node = instantiate(prefab)
      //   const randomX: number = Math.random() * 2000 - 500
      //   const randomY: number = Math.random() * 540 - 360
      //   node.setPosition(randomX, randomY)
      //   let monster = node.addComponent(Monster)
      //   this.nodeRoleParent.addChild(node)
      //   monster.init(data.monsterType)
      //   GlobalData.instance.arrNodeMonster.push(node)
      // }
      
      const delayY: number = 1300
      for (let i: number = 0; i < data.pos.length; i++) {
        let node = instantiate(prefab)
        node.setPosition(data.pos[i][0] + delayY, data.pos[i][1])
        this.scheduleOnce(() => {
          let monster: Monster = null
          const monsterData: any = GlobalData.instance.monsterData[data.monsterType]
          if (monsterData) {
            if (monsterData.isGet == 1) {
              monster = node.addComponent(MonsterHero)
            } else if (monsterData.isGet == 2) {
              monster = node.addComponent(MonsterBoss)
              // this.initNodeBossHp()
            } else {
              monster = node.addComponent(Monster)
            }
          }
          monster.init(data.monsterType)
          this.nodeRoleParent.addChild(node)

          GlobalData.instance.arrNodeMonster.push(node)
        }, time)
      }
    })
  }

  private initNodeBossHp() {
    ResManager.instance.loadRes("prefabs/game/gameObject/nodeBossHp", Prefab, (err, prefab: Prefab) => {
      let node = instantiate(prefab)
      this.nodeHpParent.addChild(node)
      node.setPosition(360, 216)
      node.alpha = 0
      new Tween(node).to(0.3, { alpha: 1 }).start()
    })
  }

  /**怪物被攻击时的伤害显示 */
  private onInitDamage(pos: Vec3, value: number) {
    // return
    ResManager.instance.loadRes("prefabs/game/gameObject/labDamage", Prefab, (err, prefab: Prefab) => {
      let node = instantiate(prefab)
      this.nodeDamageParent.addChild(node)
      node.setPosition(pos.x + Math.random() * 80 - 40, pos.y + 30)
      let labDamage: Label = node.getComponent(Label)
      labDamage.string = value + ""
      let moveY: number = node.positionY + 40
      const scale = node.scaleX
      node.scaleXYZ = 0
      new Tween(node).to(0.3, { scaleXYZ: scale }, { easing: "backOut" }).start()
      new Tween(node)
        .to(0.3, { positionY: moveY })
        .delay(0.5)
        .call(() => {
          node.destroy()
        })
        .start()
    })
  }

  update(deltaTime: number) {
    // this.onMonsterBeAttackEffect(new Vec3(0,0))
  }

  playMusic() {
    AudioManager.instance.playMusic("bm_bgm")
  }

  /**升级特效 */
  private onSkillUpgradeChange() {
    GlobalData.instance.numMonsterSlow = 2
    AudioManager.instance.playEffect("sm_upgrade")
    if (this.arrUpGradeEffect.length > 0) {
      this.playUpGradeEffect()
    } else {
      this.onCreateUpgradeEffect()
    }
  }
  private arrUpGradeEffect: Node[] = []
  private onCreateUpgradeEffect() {
    ResManager.instance.loadRes("prefabs/game/effect/effect_upgrade", Prefab, (err, prefab: Prefab) => {
      if (prefab) {
        for (let i: number = 0; i < this.arrNodeTouch.length; i++) {
          let node = instantiate(prefab)
          this.nodeEffectParent.addChild(node)
          const pos = this.arrNodeTouch[i].getPosition()
          node.setPosition(pos.x, pos.y + 40)
          node.active = false
          this.arrUpGradeEffect.push(node)
        }
        this.scheduleOnce(this.playUpGradeEffect)
      }
    })
  }

  private playUpGradeEffect() {
    for (let i: number = 0; i < this.arrRolePlayer.length; i++) {
      if (this.arrRolePlayer[i] && !this.arrRolePlayer[i].isDie) {
        this.arrUpGradeEffect[i].active = true
        let animation: Animation = this.arrUpGradeEffect[i].getComponent(Animation)
        animation.play()
      } else {
        this.arrUpGradeEffect[i].active = false
      }
    }
  }

  /**敌人被攻击特效 */
  private onMonsterBeAttackEffect(pos: Vec3) {
    ResManager.instance.loadRes("prefabs/game/effect/effect_beAttack", Prefab, (err, prefab: Prefab) => {
      let node = instantiate(prefab)
      this.nodeEffectParent.addChild(node)
      node.setPosition(pos)
      new Tween(node)
        .delay(1)
        .call(() => {
          node.destroy()
        })
        .start()
    })
  }

  /**奖励金币效果 */
  private playNodeRewardCoinValue(goldDrop: number, pos: Vec3) {
    const preCoin: Prefab = ResManager.instance.getRes("prefabs/game/gameObject/nodeRewardCoin", Prefab)
    const nodeCoin = instantiate(preCoin)
    const labValue = nodeCoin.getChildByName("label").getComponent(Label)
    labValue.string = goldDrop + ""
    nodeCoin.setPosition(pos.x, pos.y)
    this.nodeDamageParent.addChild(nodeCoin)
    nodeCoin.scaleXYZ = 0
    new Tween(nodeCoin).to(0.3, { scaleXYZ: 0.6 }, { easing: "backOut" }).start()
    new Tween(nodeCoin)
      .by(0.3, { positionY: 50 })
      .delay(0.3)
      .call(() => {
        nodeCoin.destroy()
      })
      .start()
  }

  // -----------------新手指导部分------------------
  private nodeGuide: Node = null


  private overGuideChangeRole() {
    if (GlobalData.instance.gCurrGuide == GUIDE_STATE.ROLE_CHANGER_ROLE) {
      GlobalData.instance.gCurrGuide = GUIDE_STATE.ROLE_CHANGER_COMPLETE
      this.gameResume()
      if (this.nodeGuide) {
        this.nodeGuide.destroy()
        this.nodeGuide = null
      }
    }
  }

  //指导玩家移动
  private onGuideChangeRole(firstPos: Vec3, secondPos: Vec3) {
    this.nodeGuide = this.createGuideHand()
    const guideHand: GuideHand = this.nodeGuide.getComponent(GuideHand)
    this.nodeGuide.parent = this.nodeEffectParent
    guideHand.initGuideMovePos(firstPos, secondPos)
  }

  private createGuideHand() {
    const prefab: Prefab = ResManager.instance.getRes("prefabs/game/gameObject/guideHand", Prefab)
    return prefab ? instantiate(prefab) : null
  }
  /**震动 */
  public shake() {
    const move: number = 8
    const time: number = 0.05
    new Tween(this.node)
      .to(time, { position: new Vec3(0, -move) })
      .to(time * 2, { position: new Vec3(0, move) })
      .to(time, { position: new Vec3(-move, 0) })
      .to(time * 2, { position: new Vec3(move, 0) })
      .to(time, { position: new Vec3(0, 0) })
      .start()
  }
}
